#!/bin/bash

run_user=`whoami`

if [ 'X'$run_user != 'X''root' ]
then
    echo 'Error! should run me with root...'
    exit 1
fi

cnt=`ps aux | grep postgres | grep -v $0 | grep -v 'grep' | wc -l`
if [ $cnt -gt 0 ]
then
    echo "ERROR! pg may be running, exit..."
    exit 10
fi

# recommend: don't change it
INSTALL_HOME="/usr/local/pgsql"
if [ -d ${INSTALL_HOME} ]
then
    echo "ERROR! pg home:${INSTALL_HOME} exists, exit..."
    exit 10
fi

# pg data path, can change to your another disk if needed
PG_DATA_PATH="/usr/local/pgsql/data"
if [ -d ${PG_DATA_PATH} ]
then
    echo "ERROR! data dir:${PG_DATA_PATH} exists, exit..."
    exit 10
fi

# absolute path of pg tarball used. if not give, will download pg tarball from Internet
TARBALL_PATH=''

# absolute path of pg configuration file used, defaults to '/tmp/pg_env.config'
PG_CONF_PATH=''


usage() { 
  echo -e "
Usage:
  $0 [-f ARCHIVE_TARBARR_PATH] [-c CONFIGURATION_PATH]
Common options:
  -f,  file, absolute path of archive tarball. Without -f options will download tarball from Internet
  -c,  conf,  absolute path of configuration file, default to "'`/tmp/pg_env.config`'"
" 1>&2; exit 1;
}

while getopts ":f:c:" o; do
    case "${o}" in
        f)
            v=${OPTARG}
            if [ 'X'$v == 'X' ]
            then
              usage
            else
              TARBALL_PATH=${OPTARG}
            fi
            ;;
        c)
            v=${OPTARG}
            if [ 'X'$v == 'X' ]
            then
              usage
            else
              PG_CONF_PATH=${OPTARG}
            fi
            ;;
        *)
            usage
            ;;
    esac
done
shift $((OPTIND-1))


if [ 'X'${TARBALL_PATH} == 'X' ]
then
    # version used when no tarball give
    DEFAULT_VERSION=14.5
    
    # tarball='postgresql-14.5.tar.gz'
    tarball="postgresql-${DEFAULT_VERSION}.tar.gz"
    TARBALL_PATH="/tmp/${tarball}"

    if [ -f ${TARBALL_PATH} ]
    then
        rm -rf ${TARBALL_PATH}
    fi
    echo "not give pg tarball absolute path, will download ${tarball} from Internet"
    # https://ftp.postgresql.org/pub/source/v14.5/postgresql-14.5.tar.gz
    curl https://ftp.postgresql.org/pub/source/v${DEFAULT_VERSION}/${tarball} --output ${TARBALL_PATH}
fi
if [ ! -f ${TARBALL_PATH} ]
then
    echo "ERROR! pg tarball:${TARBALL_PATH} not found, exit..."
    exit 11
fi


if [ 'X'${PG_CONF_PATH} == 'X' ]
then
    PG_CONF_PATH='/tmp/pg_env.config'
    echo "not give pg configuration file absolute path, will use default path: ${PG_CONF_PATH}"
fi

remove_pg_centos(){
    cd /
    # stop pg process
    systemctl stop postgresql
    chkconfig postgresql off
    chkconfig --del postgresql
    rm -rf /etc/init.d/postgresql
    
    # remove postgres* with yum
    yum remove postgres* -y
    
    # del previous postgres user
    userdel postgres
    groupdel postgres
}

install_libs_centos(){
    cd /
    yum update -y
    yum install gcc gcc-c++ make -y

    yum install -y bison-devel readline-devel zlib-devel openssl-devel wget ccache
    
    # install dos2unix to process some text files
    yum install dos2unix -y
}

remove_pg_ubuntu(){
    cd /
    # stop postgres process
    systemctl stop postgresql
    update-rc.d remove postgresql
    rm -rf /etc/init.d/postgresql

    # remove mariadb* and mysql* with yum
    apt-get remove postgres* -y
    
    # del previous postgres user
    userdel postgres
    groupdel postgres
}

install_libs_ubuntu(){
    cd /
    apt-get update -y
    apt-get install -y build-essential libreadline-dev zlib1g-dev flex bison libxml2-dev libxslt-dev libssl-dev libxml2-utils xsltproc ccache

    # install dos2unix to process some text files
    apt-get install dos2unix -y
}

is_centos=`awk -F '=' '/PRETTY_NAME/ { print $2 }' /etc/os-release | grep -i centos | wc -l`
is_ubuntu=`awk -F '=' '/PRETTY_NAME/ { print $2 }' /etc/os-release | grep -i ubuntu | wc -l`


if [ $is_centos -gt 0 ]
then
    # stop pg process, and del previous postgres user
    remove_pg_centos
    # install libs
    install_libs_centos
fi

if [ $is_ubuntu -gt 0 ]
then
    # stop pg process, and del previous postgres user
    remove_pg_ubuntu
    # install libs
    install_libs_ubuntu
fi

groupadd postgres
useradd -g postgres postgres


echo 'prepare install pg, please wait...'

cd /tmp
if [ -d /tmp/pg_packages ]
then
    rm -rf /tmp/pg_packages
fi
mkdir -p /tmp/pg_packages


if [ -d ${INSTALL_HOME} ]
then
    rm -rf ${INSTALL_HOME}
fi
mkdir -p ${INSTALL_HOME}

if [ ! -d ${PG_DATA_PATH} ]
then
    mkdir -p ${PG_DATA_PATH}
fi

cd /tmp/pg_packages
tar -xzvf ${TARBALL_PATH} -C /tmp/pg_packages --strip-components 1

./configure --prefix=${INSTALL_HOME} --with-openssl
make install

# exit with error if make pg fail
ret=$?

if [ 'X'$ret != 'X'0 ]
then
    make distclean
    echo 'Error! make pg failed...'
    exit 9
fi

cd ${INSTALL_HOME}
mkdir ${INSTALL_HOME}/etc

cd ${INSTALL_HOME}/etc

# load pg config from custom configs files
# clear previous env
export pg_port=
export pg_postgres_password=

if [ -f ${PG_CONF_PATH} ]
then
    dos2unix ${PG_CONF_PATH}
    . ${PG_CONF_PATH}
else
    echo "${PG_CONF_PATH} not found, will use pg default port and password"
fi

if [ 'X'${pg_port} == 'X' ]
then
    pg_port=5432
    echo "use pg default port: ${pg_port}"
fi

if [ 'X'${pg_postgres_password} == 'X' ]
then
    pg_postgres_password='postgres.123'
    echo "use pg default password: ${pg_postgres_password}"
fi

chown -R postgres:postgres ${INSTALL_HOME}
chmod -R 700 ${PG_DATA_PATH}

# use user postgres to init postgres-server
su - postgres <<EOF
cd ${INSTALL_HOME}
${INSTALL_HOME}/bin/initdb -D ${PG_DATA_PATH}

# set some config
echo "" >> ${PG_DATA_PATH}/postgresql.conf
echo "# configs added when install pg" >> ${PG_DATA_PATH}/postgresql.conf

# pg listen host
sed -i "s/listen_addresses =/#listen_addresses =/g" ${PG_DATA_PATH}/postgresql.conf
echo "listen_addresses = '0.0.0.0'" >> ${PG_DATA_PATH}/postgresql.conf

# pg listen port
sed -i "s/port =/#port =/g" ${PG_DATA_PATH}/postgresql.conf
echo "port = ${pg_port}" >> ${PG_DATA_PATH}/postgresql.conf

# pg data dir
sed -i "s/data_directory =/#data_directory =/g" ${PG_DATA_PATH}/postgresql.conf
echo "data_directory = '${PG_DATA_PATH}'" >> ${PG_DATA_PATH}/postgresql.conf

# alter Client Authentication Configuration File to accepts connections from everywhere with sha encrypted passwords
echo '# Allow connections from everywhere, with sha password' >> ${PG_DATA_PATH}/pg_hba.conf
echo 'host    all             all             0.0.0.0/0               scram-sha-256' >> ${PG_DATA_PATH}/pg_hba.conf


export PGDATA=${PG_DATA_PATH}

${INSTALL_HOME}/bin/pg_ctl -D ${PG_DATA_PATH} start

sleep 5
# change user postgres password
${INSTALL_HOME}/bin/psql postgres -hlocalhost -p${pg_port} -Upostgres -c "alter user postgres with password '${pg_postgres_password}';"

sleep 5
${INSTALL_HOME}/bin/pg_ctl -D ${PG_DATA_PATH} stop


echo "pg installed in ${INSTALL_HOME}, conf file in ${PG_DATA_PATH}"
EOF

# use start-scripts in contrib to start postgresql-server when the computer boots
cp -r /tmp/pg_packages/contrib/start-scripts ${INSTALL_HOME}
chown -R postgres:postgres ${INSTALL_HOME}/start-scripts
cd ${INSTALL_HOME}/start-scripts

sed -i "s|prefix=/usr/local/pgsql|prefix=${INSTALL_HOME}|g" ${INSTALL_HOME}/start-scripts/linux
sed -i "s|PGDATA=\"/usr/local/pgsql/data\"|PGDATA=\"${PG_DATA_PATH}\"|g" ${INSTALL_HOME}/start-scripts/linux
chmod +x linux
echo "postgresql start scripts is ${INSTALL_HOME}/start-scripts/linux, can edit it for more settings"

start_on_boot_centos(){
    # add pg to service use chkconfig
    cd ${INSTALL_HOME}/start-scripts/
    ln -s ${INSTALL_HOME}/start-scripts/linux /etc/init.d/postgresql
    chkconfig --add postgresql
    chkconfig postgresql on
}

start_on_boot_ubuntu(){
    # add pg to service use update-rc.d
    cd ${INSTALL_HOME}/start-scripts/
    # add init info in start script
    line_num=`cat linux | grep -n '#! /bin/sh' | awk -F':' '{print $1}'`
    line_num=`echo ${line_num}+1|bc`
    sed -i "${line_num}"'i\
### BEGIN INIT INFO\
# Provides:          postgresql\
# Required-Start:    $all\
# Required-Stop:\
# Default-Start:     2 3 4 5\
# Default-Stop:     0 1 6\
# Short-Description: postgresql...\
### END INIT INFO
    ' linux

    ln -s ${INSTALL_HOME}/start-scripts/linux /etc/init.d/postgresql
    update-rc.d postgresql defaults
}

if [ $is_centos -gt 0 ]
then
    # start mysql on boot
    start_on_boot_centos
fi

if [ $is_ubuntu -gt 0 ]
then
    # start mysql on boot
    start_on_boot_ubuntu
fi

systemctl daemon-reload

rm -rf /tmp/pg_packages

echo "install and initialize pg completed, will start pg server now"
sleep 5

systemctl start postgresql
echo "postgresql start with data dir: ${PG_DATA_PATH}, log path: ${PG_DATA_PATH}/serverlog"

echo "pg start and will automatically start on boot, use 'systemctl status postgresql' to check"
